home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / emulator / bsvc-1.000 / bsvc-1 / bsvc-1.0.4 / src / Assemblers / 68kasm / eval.c < prev    next >
C/C++ Source or Header  |  1995-07-26  |  11KB  |  423 lines

  1. /******************************************************************************
  2.  * $Id: eval.c,v 1.1 1994/08/29 23:58:22 bmott Exp $
  3.  ******************************************************************************
  4.  *
  5.  *        EVAL.C
  6.  *        Expression Evaluator for 68000 Assembler
  7.  *
  8.  *    Function: eval()
  9.  *        Evaluates a constant expression. The p argument points
  10.  *        to the string to be evaluated, and the function returns
  11.  *        a pointer to the first character beyond the end of the
  12.  *        expression. The value of the expression and an error
  13.  *        code are returned via output arguments. The function 
  14.  *        handles errors according to the following table:
  15.  *
  16.  *                   Pass1        Pass1   Pass2         Pass2
  17.  *        Condition          Error        *refPtr Error         *refPtr
  18.  *        ----------------   ----------   -----   -----------   -----
  19.  *        Undefined symbol   INCOMPLETE   FALSE   UNDEFINED     FALSE
  20.  *        Division by zero   INCOMPLETE   FALSE   DIV_BY_ZERO   FALSE
  21.  *        Syntax error       SYNTAX      --      SYNTAX        --
  22.  *         Constant error     x_TOO_BIG    T/F     x_TOO_BIG     T/F
  23.  *        No error           OK           T/F     OK            T/F
  24.  *
  25.  *        The char pointed to by refPtr is set to TRUE if all the
  26.  *        symbols encountered in the expression are backwards
  27.  *        references or FALSE if at least one symbol is a forward
  28.  *        reference. 
  29.  *
  30.  *     Usage:    char *eval(p, valuePtr, refPtr, errorPtr)
  31.  *        char *p;
  32.  *        int *valuePtr;
  33.  *        char *refPtr;
  34.  *        int *errorPtr;
  35.  *
  36.  *    Errors: ASCII_TOO_BIG
  37.  *        DIV_BY_ZERO
  38.  *        INCOMPLETE
  39.  *        NUMBER_TOO_BIG
  40.  *        REG_LIST_SPEC
  41.  *        SYNTAX
  42.  *        UNDEFINED
  43.  *
  44.  *      Author: Paul McKee
  45.  *        ECE492    North Carolina State University
  46.  *
  47.  *        Date:    9/24/86
  48.  *
  49.  *   Copyright 1990-1991 North Carolina State University. All Rights Reserved.
  50.  *
  51.  ******************************************************************************
  52.  * $Log: eval.c,v $
  53.  * Revision 1.1  1994/08/29  23:58:22  bmott
  54.  * Initial revision
  55.  *
  56.  *****************************************************************************/
  57.  
  58.  
  59. #include <stdio.h>
  60. #include <ctype.h>
  61. #include "asm.h"
  62.  
  63. extern char pass2;
  64. extern int loc;
  65.  
  66. /* Largest number that can be represented in an unsigned int - MACHINE DEPENDENT */
  67. #define INTLIMIT 0xFFFFFFFF
  68.  
  69. #define STACKMAX 5
  70.  
  71. char *eval(p, valuePtr, refPtr, errorPtr)
  72. char *p;
  73. int *valuePtr;
  74. char *refPtr;
  75. int *errorPtr;
  76. {
  77. char *evalNumber();
  78. int valStack[STACKMAX], opStack[STACKMAX-1];
  79. int valPtr = 0, opPtr = 0;
  80. int op;
  81. int t, prec;
  82. int i;
  83. char evaluate, backRef;
  84. int status;
  85.  
  86. /*    printf("EVAL: Input string is \"%s\"\n", p); */
  87.     /* Assume that the expression is to be evaluated,
  88.        at least until an undefined symbol is found */
  89.     evaluate = TRUE;
  90.     /* Assume initially that all symbols are backwards references */
  91.     *refPtr = TRUE;
  92.     /* Loop until terminator character is found (loop is exited via return) */
  93.     while (TRUE) {
  94.         /************************************************
  95.          *                        *
  96.          *        EXPECT AN OPERAND        *
  97.          *                        *
  98.          ************************************************/
  99.         /* Use evalNumber to read in a number or symbol */
  100.         status = OK;
  101.         p = evalNumber(p, &t, &backRef, &status);
  102.         NEWERROR(*errorPtr, status);
  103.         if (!backRef && (status > ERROR || status == INCOMPLETE)) {
  104.             /* Stop evaluating the expression */
  105.             evaluate = FALSE;
  106.             *refPtr = FALSE;
  107.             }
  108.         else if (*errorPtr > SEVERE)
  109.             /* Pass any other error to the caller */
  110.             return NULL;
  111.         else {
  112.             /* If OK or WARNING, push the value on the stack */
  113.             if (evaluate)
  114.                 valStack[valPtr++] = t;
  115.             /* Set *refPtr to reflect the symbol just parsed */
  116.             *refPtr = *refPtr && backRef;
  117.             }
  118. /*        printf("Operand read - stack contains (bottom to top):\n");
  119.         for (i = 0; i < valPtr || i < opPtr; i++) {
  120.             printf("%2d: ", i);
  121.             if (i < valPtr)
  122.                 printf("%10d ", valStack[i]);
  123.             else
  124.                 printf("           ");
  125.             if (i < opPtr)
  126.                 putchar(opStack[i]);
  127.             putchar('\n');
  128.             } */
  129.  
  130.         /************************************************
  131.          *                        *
  132.          *        EXPECT AN OPERATOR        *
  133.          *                        *
  134.          ************************************************/
  135.         /* Handle the >> and << operators */
  136.         if (*p == '>' || *p == '<') {
  137.             p++;
  138.             if (*p != *(p-1)) {
  139.                 NEWERROR(*errorPtr, SYNTAX);
  140.                 return NULL;
  141.                 }
  142.             }
  143.         prec = precedence(*p);
  144.         /* Do all stacked operations that are of higher
  145.            precedence than the operator just examined. */
  146.         while (opPtr && evaluate && (prec <= precedence(opStack[opPtr-1]))) {
  147.             /* Pop operands and operator and do the operation */
  148.             t = valStack[--valPtr];
  149.             i = valStack[--valPtr];
  150.             status = doOp(i, t, opStack[--opPtr], &t);
  151.             if (status != OK) {
  152.                 /* Report error from doOp */
  153.                 if (pass2) {
  154.                     NEWERROR(*errorPtr, status);
  155.                     }
  156.                 else
  157.                     NEWERROR(*errorPtr, INCOMPLETE);
  158.                 evaluate = FALSE;
  159.                 *refPtr = FALSE;
  160.                 }
  161.             else
  162.                 /* Otherwise push result on the stack */
  163.                 valStack[valPtr++] = t;
  164.             }
  165.         if (prec) {
  166.             if (evaluate)
  167.                 /* If operator is valid, push it on the stack */
  168.                 opStack[opPtr++] = *p;
  169.             p++;
  170.             }
  171.         else if (*p == ',' || *p == '(' || *p == ')' || !(*p) || isspace(*p)) {
  172.             /* If the character terminates the expression,
  173.                then return the various results needed. */
  174.             if (evaluate)
  175.                 *valuePtr = valStack[--valPtr];
  176.             else
  177.                 *valuePtr = 0;
  178. /*            printf("EVAL: The expression is \"");
  179.             while (start < p)
  180.                 putchar(*start++);
  181.             printf("\"\n"); */
  182.             return p;
  183.             }
  184.         else {
  185.             /* Otherwise report the syntax error */
  186.             NEWERROR(*errorPtr,  SYNTAX);
  187.             return NULL;
  188.             }
  189.  
  190. /*        printf("Operator processed - stack contains (bottom to top):\n");
  191.         for (i = 0; i < valPtr || i < opPtr; i++) {
  192.             printf("%2d: ", i);
  193.             if (i < valPtr)
  194.                 printf("%10d ", valStack[i]);
  195.             else
  196.                 printf("           ");
  197.             if (i < opPtr)
  198.                 putchar(opStack[i]);
  199.             putchar('\n');
  200.             } */
  201.         }
  202. }
  203.  
  204.  
  205. char *evalNumber(p, numberPtr, refPtr, errorPtr)
  206. char *p;
  207. int *numberPtr;
  208. char *refPtr;
  209. int *errorPtr;
  210. {
  211. int status, x, base;
  212. char name[SIGCHARS+1];
  213. symbolDef *symbol, *lookup();
  214. int i;
  215. char endFlag;
  216.  
  217.     *refPtr = TRUE;
  218.     if (*p == '-') {
  219.         /* Evaluate unary minus operator recursively */
  220.         p = evalNumber(++p, &x, refPtr, errorPtr);
  221.         *numberPtr = -x;
  222.         return p;
  223.         }
  224.     else if (*p == '~') {
  225.         /* Evaluate one's complement operator recursively */
  226.         p = evalNumber(++p, &x, refPtr, errorPtr);
  227.         *numberPtr = ~x;
  228.         return p;
  229.         }
  230.     else if (*p == '(') {
  231.         /* Evaluate parenthesized expressions recursively */
  232.         p = eval(++p, &x, refPtr, errorPtr);
  233.         if (*errorPtr > SEVERE)
  234.             return NULL;
  235.         else if (*p != ')') {
  236.             NEWERROR(*errorPtr, SYNTAX);
  237.             return NULL;
  238.             }
  239.         else {
  240.             *numberPtr = x;
  241.             return ++p;
  242.             }
  243.         }
  244.     else if (*p == '$' && isxdigit(*(p+1))) {
  245.         /* Convert hex digits until another character is
  246.            found. (At least one hex digit is present.) */
  247.         x = 0;
  248.         while (isxdigit(*++p)) {
  249.             if ((unsigned)x > (unsigned)INTLIMIT/16)
  250.                 NEWERROR(*errorPtr, NUMBER_TOO_BIG);
  251.             if (*p > '9')
  252.                 x = 16 * x + (*p - 'A' + 10);
  253.             else
  254.                 x = 16 * x + (*p - '0');
  255.             }
  256.         *numberPtr = x;
  257.         return p;
  258.         }
  259.     else if (*p == '%' || *p == '@' || isdigit(*p)) {
  260.         /* Convert digits in the appropriate base (binary, 
  261.            octal, or decimal) until an invalid digit is found. */
  262.         if (*p == '%') {
  263.             base = 2;
  264.             p++;
  265.             }
  266.         else if (*p == '@') {
  267.             base = 8;
  268.             p++;
  269.             }
  270.         else base = 10;
  271.         /* Check that at least one digit is present */
  272.         if (*p < '0' || *p >= '0' + base) {
  273.             NEWERROR(*errorPtr, SYNTAX);
  274.             return NULL;
  275.             }
  276.         x = 0;
  277.         /* Convert the digits into an integer */
  278.         while (*p >= '0' && *p < '0' + base) {
  279.             if ((unsigned)x > (unsigned)(INTLIMIT - (*p-'0'))/base)
  280.                 NEWERROR(*errorPtr, NUMBER_TOO_BIG);
  281.             x = base * x + (*p - '0');
  282.             p++;
  283.             }
  284.         *numberPtr = x;
  285.         return p;
  286.         }
  287.     else if (*p == '\'') {
  288.         endFlag = FALSE;
  289.         i = 0;
  290.         x = 0;
  291.         p++;
  292.         while (!endFlag) {
  293.             if (*p == '\'') 
  294.                 if (*(p+1) == '\'') {
  295.                     x = (x << 8) + *p;
  296.                     i++;
  297.                     p++;
  298.                     }
  299.                 else
  300.                     endFlag = TRUE;
  301.             else {
  302.                 x = (x << 8) + *p;
  303.                 i++;
  304.                 }
  305.             p++;
  306.             }
  307.         if (i == 0) {
  308.             NEWERROR(*errorPtr, SYNTAX);
  309.             return NULL;
  310.             }
  311.         else if (i == 3)
  312.             x = x << 8;
  313.         else if (i > 4)
  314.             NEWERROR(*errorPtr, ASCII_TOO_BIG);
  315.         *numberPtr = x;
  316.         return p;
  317.         }
  318.     else if (isalpha(*p) || *p == '.') {
  319.         /* Determine the value of a symbol */
  320.         i = 0;
  321.         /* Collect characters of the symbol's name
  322.            (only SIGCHARS characters are significant) */
  323.         do {
  324.             if (i < SIGCHARS)
  325.                 name[i++] = *p;
  326.             p++;
  327.         } while (isalnum(*p) || *p == '.' || *p == '_' || *p == '$');
  328.         name[i] = '\0';
  329.         /* Look up the name in the symbol table, resulting
  330.            in a pointer to the symbol table entry */
  331.         status = OK;
  332.         symbol = lookup(name, FALSE, &status);
  333. /*        printf("EvalNumber: Status from lookup = %04X\n", status); */
  334.         if (status == OK)
  335.             /* If symbol was found, and it's not a register
  336.                list symbol, then return its value */
  337.             if (!(symbol->flags & REG_LIST_SYM)) {
  338.                 *numberPtr = symbol->value;
  339. /*                printf("The value of the symbol \"%s\" is %08X\n",
  340.                     name, *numberPtr); */
  341.                 if (pass2)
  342.                     *refPtr = (symbol->flags & BACKREF);
  343.                 }
  344.             else {
  345.                 /* If it is a register list symbol, return error */
  346.                 *numberPtr = 0;
  347.                 NEWERROR(*errorPtr, REG_LIST_SPEC);
  348.                 }
  349.         else {
  350.             /* Otherwise return an error */
  351.             if (pass2) {
  352.                 NEWERROR(*errorPtr, UNDEFINED);
  353.                 }
  354.             else
  355.                 NEWERROR(*errorPtr, INCOMPLETE);
  356.             *refPtr = FALSE;
  357.             }
  358. /*        printf("The symbol \"%s\" is%s a backwards reference\n",
  359.             name, (*refPtr) ? "" : " not"); */
  360.         return p;
  361.          }
  362.     else {
  363.         /* Otherwise, the character was not a valid operand */
  364.         NEWERROR(*errorPtr, SYNTAX);
  365.         return NULL;
  366.         }
  367. }
  368.  
  369. int precedence(op)
  370. char op;
  371. {
  372.     /* Compute the precedence of an operator. Higher numbers indicate
  373.        higher precedence, e.g., precedence('*') > precedence('+').
  374.        Any character which is not a binary operator will be assigned
  375.        a precedence of zero. */
  376.     switch (op) {
  377.         case '+' :
  378.         case '-' : return 1;
  379.         case '&' :
  380.          case '!' : return 3;
  381.         case '>' :
  382.         case '<' : return 4;
  383.         case '*' :
  384.         case '/' : 
  385.         case '\\': return 2;
  386.         default  : return 0;
  387.         }
  388. }
  389.  
  390.  
  391. int doOp(val1, val2, op, result)
  392. int val1, val2;
  393. char op;
  394. int *result;
  395. {
  396.  
  397.     /* Performs the operation of the operator on the two operands.
  398.        Returns OK or DIV_BY_ZERO. */
  399.  
  400.     switch (op) {
  401.         case '+' : *result = val1 + val2;  return OK;
  402.         case '-' : *result = val1 - val2;  return OK;
  403.         case '&' : *result = val1 & val2;  return OK;
  404.         case '!' : *result = val1 | val2;  return OK;
  405.         case '>' : *result = val1 >> val2; return OK;
  406.         case '<' : *result = val1 << val2; return OK;
  407.         case '*' : *result = val1 * val2;  return OK;
  408.         case '/' : if (val2 != 0) {
  409.                    *result = val1 / val2;
  410.                    return OK;
  411.                    }
  412.                else
  413.                    return DIV_BY_ZERO;
  414.         case '\\': if (val2 != 0) {
  415.                    *result = val1 % val2;
  416.                    return OK;
  417.                    }
  418.                else
  419.                    return DIV_BY_ZERO;
  420.         default  : printf("DoOp: Operator error  op = '%c' val1 = %d val2 = %d\n", op, val1, val2);
  421.         }
  422. }
  423.